from PyQt4 import QtCore, QtGui
from PyQt4.Qt import QAbstractListModel, QFileDialog, QMessageBox, QModelIndex, \
    QVariant
from pyastm.comparator import SpectrogramComparator
from pyastm.dbmodel import Species, Template
from pyastm.gui.pyqt4.species import Ui_MainWindow
from pyastm.plotting import plot_spectrogram_for_signal
from pyastm.signal import read_signal_from_string
import winsound




class MySpeciesWindow(QtGui.QMainWindow):
    def __init__(self, applicationContext, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.application_context = applicationContext
        
        self.list_model_species = ListModelSpecies(applicationContext.species_dao)
        self.list_model_template = ListModelTemplate(applicationContext.template_dao)
        
        self.comparator = SpectrogramComparator(applicationContext)
        
        # load frequency snapshots
        self.ui.listViewSpecies.setModel(self.list_model_species)
        self.ui.comboSpecies.setModel(self.list_model_species)
        self.ui.listViewTemplates.setModel(self.list_model_template)
        
        # load sounds for the first selected species
        self.load_templates()
        
    def load_templates(self):
        selected_species = self.list_model_species.data(self.ui.comboSpecies.currentIndex(), QtCore.Qt.UserRole)
        if selected_species:
            self.list_model_template.load_templates_for_species(selected_species)
        
    def add_template(self):
        file = open(QFileDialog.getOpenFileName(self, 'Choose WAV file', ''), 'rb')
        selectedSpecies = self.list_model_species.data(self.ui.comboSpecies.currentIndex(), QtCore.Qt.UserRole)
        template = Template(None, selectedSpecies.id, None)
        self.list_model_template.add_template(template, file.read())
        file.close()
    
    def delete_template(self):
        selectedSound = self.list_model_template.data(self.ui.listViewTemplates.currentIndex(), QtCore.Qt.UserRole)
        self.list_model_template.delete_template(selectedSound)
        
    def play_template(self):
        selectedTemplate = self.list_model_template.data(self.ui.listViewTemplates.currentIndex(), QtCore.Qt.UserRole)
        if isinstance(selectedTemplate, Template):
            winsound.PlaySound(self.list_model_template.load_sound_data(selectedTemplate), winsound.SND_MEMORY)
        
    def replace_template(self):
        file = open(QFileDialog.getOpenFileName(self, 'Choose WAV file', ''), 'rb')
        selectedSound = self.list_model_template.data(self.ui.listViewTemplates.currentIndex(), QtCore.Qt.UserRole)
        self.list_model_template.replace_template(selectedSound, file.read())
        file.close()
        
    def show_spectrogram(self):
        selected_template = self.list_model_template.data(self.ui.listViewTemplates.currentIndex(), QtCore.Qt.UserRole)
        if isinstance(selected_template, Template):
            config = self.application_context.fftconfig
            
            fftlen = int(config['fftlen'])
            samplespersecond = int(config['samplespersecond'])
            
            data = self.list_model_template.load_sound_data(selected_template)
            template_signal, template_signal_sampling_freq = read_signal_from_string(data)
            plot_spectrogram_for_signal(template_signal, fftlen, template_signal_sampling_freq, samplespersecond)
            
    def load_audio_track(self):
        # open the audio track
        file = open(QFileDialog.getOpenFileName(self, 'Choose WAV file', ''), 'rb')
        self.ui.lineEditAudioTrackFile.setText(file.name)
        
    def play_audio_track(self):
        if self.ui.lineEditAudioTrackFile.text():
            winsound.PlaySound(str(self.ui.lineEditAudioTrackFile.text()), winsound.SND_FILENAME)

    def go(self):
        if self.ui.lineEditAudioTrackFile.text():
            results = self.comparator.compare_audio_track_against_db(str(self.ui.lineEditAudioTrackFile.text()))
            # let's display first three best matches for now
            sortedResults = sorted(results, key=lambda correlation_value: correlation_value[1], reverse=True)
            message = 'A list of best matches:\n'
            for result in sortedResults:
                species = self.application_context.species_dao.get_species_by_id(result[0].id_species)
                message = message + species.name.decode('UTF-8') + ' (template id ' + str(result[0].id) + '), correlation value ' + str(result[1]) + '\n'
                print message
            QMessageBox.information(self, 'Result', message)
    
    def add_species(self):
        name = self.ui.lineEditSpecies.text()
        if name:
            self.list_model_species.add_species(str(name))
        self.ui.lineEditSpecies.clear()
        
    def delete_species(self):
        selectedSpecies = self.list_model_species.data(self.ui.listViewSpecies.currentIndex(), QtCore.Qt.UserRole)
        self.list_model_species.delete_species(selectedSpecies)
        

class ListModelSpecies(QAbstractListModel):
    def __init__(self, species_dao, parent=None):
        QAbstractListModel.__init__(self, parent)
        self.species_dao = species_dao
        self.species = species_dao.get_species_list()
    
    def rowCount(self, parent=QModelIndex()):
        return len(self.species)
    
    def data(self, index, role):
        if isinstance(index, QModelIndex):
            if index.isValid():
                if role == QtCore.Qt.UserRole:
                    return self.species[index.row()]
                elif role == QtCore.Qt.DisplayRole:
                    return QVariant(self.species[index.row()].name.decode('UTF-8'))
            else:
                return QVariant()
        elif isinstance(index, int):
            if index > -1:
                return self.species[index]
            else:
                return None
            
    def add_species(self, name):
        species = Species(None, name, None)
        self.species.append(self.species_dao.insert_species(species))
        self.reset()
        
    def delete_species(self, species):
        self.species_dao.delete_species(species)
        self.species.remove(species)
        self.reset()
        

class ListModelTemplate(QAbstractListModel):
    def __init__(self, template_dao, parent=None):
        QAbstractListModel.__init__(self, parent)
        self.template_dao = template_dao
        self.sounds = []
        
    def rowCount(self, parent=QModelIndex()):
        return len(self.sounds)
    
    def data(self, index, role):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                return QVariant(str(self.sounds[index.row()].id))
            elif role == QtCore.Qt.UserRole:
                return self.sounds[index.row()]
        else:
            return QVariant()
        
    def add_template(self, template, data):
        self.sounds.append(self.template_dao.insert_template(template))
        self.template_dao.save_template_sound_data(template, data)
        self.reset()
        
    def replace_template(self, template, data):
        self.template_dao.update_template(template)
        self.template_dao.save_template_sound_data(data)
        self.reset()
        
    def delete_template(self, template):
        self.sounds.remove(template)
        self.template_dao.delete_template(template)
        self.reset()
        
    def load_sound_data(self, template):
        return self.template_dao.load_sound_data_for_template(template)
        
    def load_templates_for_species(self, species):
        self.sounds = self.template_dao.get_templates_for_species(species)
        self.reset()
